import { Injectable, UnauthorizedException, NotFoundException, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { User, UserWhitelist, UserDevice } from './entities/login.entity';
import { RegisterDto, LoginDto, ChangePasswordDto } from './dto/login.dto';
import { CreateDeviceDto, UpdateDeviceDto } from './dto/device.dto';
import { TDevice } from '../t_device/entities/t-device.entity';
import * as jwt from 'jsonwebtoken';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class LoginService {
  private readonly SALT_ROUNDS = 10;

  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    @InjectRepository(UserWhitelist)
    private readonly whitelistRepository: Repository<UserWhitelist>,
    @InjectRepository(UserDevice)
    private readonly deviceRepository: Repository<UserDevice>,
    @InjectRepository(TDevice)
    private readonly tDeviceRepository: Repository<TDevice>,
    private readonly configService: ConfigService,
  ) {}

  private async hashPassword(password: string): Promise<string> {
    return bcrypt.hash(password, this.SALT_ROUNDS);
  }

  private async comparePasswords(plainPassword: string, hashedPassword: string): Promise<boolean> {
    return bcrypt.compare(plainPassword, hashedPassword);
  }

  async register(registerDto: RegisterDto): Promise<void> {
    const { username, password } = registerDto;

    // 检查用户是否已存在
    const existingUser = await this.userRepository.findOne({ where: { username } });
    if (existingUser) {
      throw new ConflictException('用户名已存在');
    }

    // 检查白名单
    const whitelistEntry = await this.whitelistRepository.findOne({ where: { username } });
    if (!whitelistEntry || !whitelistEntry.isEnabled) {
      throw new UnauthorizedException('用户不在白名单中或已被禁用');
    }

    //1.用t_device 表 依据 用户名查询对应的device_imei1
    const device = await this.tDeviceRepository.findOne({ where: { user_name: username } });
    if (!device) {
      throw new UnauthorizedException('未找到该用户的设备信息');
    }

    //2.如果该方法输入device_imei1 参数 和数据库查询返回的 device_imei1一致的话，通过否则提示信息device_imei1校验失败
    if (registerDto.device_imei1 !== device.device_imei1) {
      throw new UnauthorizedException('device_imei1校验失败');
    }

    // 加密密码
    const hashedPassword = await this.hashPassword(password);

    // 创建新用户
    const user = this.userRepository.create({
      username,
      password: hashedPassword,
    });

    await this.userRepository.save(user);
  }

  async login(loginDto: LoginDto): Promise<{ id: string; username: string; refreshToken: string }> {
    const { username, password } = loginDto;

    // 检查白名单
    const whitelistEntry = await this.whitelistRepository.findOne({ where: { username } });
    if (!whitelistEntry || !whitelistEntry.isEnabled) {
      throw new UnauthorizedException('用户不在白名单中或已被禁用');
    }

    // 查找用户
    const user = await this.userRepository.findOne({ where: { username } });
    if (!user) {
      throw new UnauthorizedException('用户名或密码错误');
    }

    // 验证密码
    const isPasswordValid = await this.comparePasswords(password, user.password);
    if (!isPasswordValid) {
      throw new UnauthorizedException('用户名或密码错误');
    }

    // 登录成功后生成refreshToken并写入user表
    const secret = this.configService.get<string>('JWT_SECRET');
    const refreshToken = jwt.sign({ username: user.username }, secret, { expiresIn: '7d' });
    user.refreshToken = refreshToken;
    await this.userRepository.save(user);

    return {
      id: user.id,
      username: user.username,
      refreshToken,
    };
  }

  async changePassword(userId: string, changePasswordDto: ChangePasswordDto): Promise<void> {
    const { oldPassword, newPassword } = changePasswordDto;

    // 查找用户
    const user = await this.userRepository.findOne({ where: { id: userId } });
    if (!user) {
      throw new NotFoundException('用户不存在');
    }

    // 验证旧密码
    const isPasswordValid = await this.comparePasswords(oldPassword, user.password);
    if (!isPasswordValid) {
      throw new UnauthorizedException('旧密码错误');
    }

    // 加密新密码
    const hashedPassword = await this.hashPassword(newPassword);

    // 更新密码
    user.password = hashedPassword;
    await this.userRepository.save(user);
  }

  // 设备管理相关方法
  async createDevice(createDeviceDto: CreateDeviceDto): Promise<UserDevice> {
    const device = this.deviceRepository.create(createDeviceDto);
    return await this.deviceRepository.save(device);
  }

  async findAllDevices(): Promise<UserDevice[]> {
    return await this.deviceRepository.find();
  }

  async findDeviceById(id: string): Promise<UserDevice> {
    const device = await this.deviceRepository.findOne({ where: { id } });
    if (!device) {
      throw new NotFoundException('设备不存在');
    }
    return device;
  }

  async updateDevice(id: string, updateDeviceDto: UpdateDeviceDto): Promise<UserDevice> {
    const device = await this.findDeviceById(id);
    Object.assign(device, updateDeviceDto);
    return await this.deviceRepository.save(device);
  }

  async deleteDevice(id: string): Promise<void> {
    const device = await this.findDeviceById(id);
    await this.deviceRepository.remove(device);
  }
}